/* Papastefanos Serafeim */
/* Sunarthseis gia elegxo tupwn */

#include "client.h"
#include "typechk.h"
#include "ctype.h"
#include "stdio.h"
#include "string.h"
#include "helpers.h"
#include "custom.h"
#include <stdlib.h>
#include <limits.h>

/* H sunarthsh auth pairnei mia lista parametrwn pou prokeitai na
 * perastei sthn handleSetParameterValues kai enan pinaka apo
 * akeraious, me mege9os iso me th lista paraketrwn. Elegxei ka9e
 * mia apo tis parametrous ths listas xrhsimopoiwntas thn checkParameter
 * h opoia vrisketai sto custom.c kai an uparxei provlhma
 * ti9etai sthn katallhlh 9esh tou pinaka errors h timh tou sfalmatos.
 * An ginei estw kai ena sfalma epistrefetai to -INVALID_ARGUMENTS,
 * opote h sunarthsh pou kalese thn checkSetParameterValues 9a
 * elegjei kai ton pinaka errors gia mh mhdenikes times wste na 
 * vrei pou akrivws egine to la9os / la9h. */
int checkSetParameterValues(ParameterValueList *parameterList, int *errors) {
	unsigned int i;
	int ok = 1;
	int r = 0;
	for(i=0;i<parameterList->size;i++) errors[i]=0;

	for(i=0;i<parameterList->size;i++) {
		StateVariable *sv = getStateVariable(parameterList->parameters[i].name);
		if(sv->writable==0) {
			ok = 0;
			errors[i]=-ATTEMPT_TO_SET_NON_WRITABLE;
		} else if( (r=checkParameter(parameterList->parameters[i]))!=0) {
			ok = 0;
			errors[i]=r;
		}
	}
	if(ok==0) return -INVALID_ARGUMENTS; else return 0;
}

/* Elegxei an to string buf einai katallhlou mege9ous */
int checkString(char *buf, unsigned int len) {
	if(buf == NULL) return -INTERNAL_ERROR;
	if(strlen(buf) > len) return -INVALID_PARAMETER_VALUE;
	return 0;
}

/* Elegxei an sto buf uparxei katallhlos akeraios */
int checkInt(char *buf) {
	if(buf == NULL) return -INTERNAL_ERROR;
	long int tmp = strtol(buf, NULL, 10);
	if(tmp == LONG_MAX || tmp == LONG_MIN) return -INVALID_PARAMETER_VALUE;
	int i=0;
	while(isspace(buf[i]) && buf[i]!=0 ) i++;
	if(buf[i]==0) return  -INVALID_PARAMETER_TYPE;
	if(!isdigit(buf[i])) {
		if(buf[i]!='+' && buf[i]!='-') return -INVALID_PARAMETER_TYPE;
		i++;
	}
	while(isdigit(buf[i])&& buf[i]!=0) i++;
	if(buf[i]==0) return 0;
	else if(isspace(buf[i])) {
		while(isspace(buf[i])&& buf[i]!=0) i++;
		if(buf[i]==0) return 0;
		else return -INVALID_PARAMETER_TYPE;
	} else return -INVALID_PARAMETER_TYPE;

	return 0;
}

/* Elegxei an sto buf uparxei katallhlos aproshmos akeraios */
int checkUnsignedInt(char *buf) {
	if(buf == NULL) return -INTERNAL_ERROR;
	long int tmp = strtol(buf, NULL, 10);
	if(tmp == LONG_MAX || tmp == LONG_MIN) return -INVALID_PARAMETER_VALUE;
	int i=0;
	while(isspace(buf[i]) && buf[i]!=0 ) i++;
	if(buf[i]==0) return  -INVALID_PARAMETER_TYPE;
	if(!isdigit(buf[i])) -INVALID_PARAMETER_TYPE;
	while(isdigit(buf[i])&& buf[i]!=0) i++;
	if(buf[i]==0) return 0;
	else if(isspace(buf[i])) {
		while(isspace(buf[i])&& buf[i]!=0) i++;
		if(buf[i]==0) return 0;
		else return -INVALID_PARAMETER_TYPE;
	} else return -INVALID_PARAMETER_TYPE;

	return 0;
}

/* Elegxei an sto buf uparxei 0 h 1 (boolean) */
int checkBoolean(char *buf) {
	int i=0;
	if(buf == NULL) return -INTERNAL_ERROR;
	while(isspace(buf[i]) && buf[i]!=0 ) i++;
	if(buf[i]==0) return  -INVALID_PARAMETER_TYPE;
	if( (buf[i]!='0')&& (buf[i]!='1') ) return -INVALID_PARAMETER_TYPE;
	i++;
	if(buf[i]==0) return 0;
	else if(isspace(buf[i])) {
		while(isspace(buf[i])&& buf[i]!=0) i++;
		if(buf[i]==0) return 1;
		else return -INVALID_PARAMETER_TYPE;
	} else return -INVALID_PARAMETER_TYPE;
	return 0;
}

/* Elegxei an sto buf uparxei DateTime */
int checkDateTime(char *buf) {
	int i=0;
	if(buf == NULL) return -INTERNAL_ERROR;
	while(isspace(buf[i]) && buf[i]!=0 ) i++;
	if(buf[i]==0) return  -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(buf[i]=='-') i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(buf[i]=='-') i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(buf[i]=='T') i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(buf[i]==':') i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(buf[i]==':') i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(isdigit(buf[i])) i++; else return -INVALID_PARAMETER_TYPE;
	if(buf[i]==0) return 0;
	else if(isspace(buf[i])) {
		while(isspace(buf[i])&& buf[i]!=0) i++;
		if(buf[i]==0) return 1;
		else return -INVALID_PARAMETER_TYPE;
	} else return -INVALID_PARAMETER_TYPE;
	return 0;
}

/* Elegxei an sto buf uparxei base64 mege9ous len. Ena base64 string 
 * epitrepetai na exei tous xarakthres A-Z, a-z, 0-9, +, / kai =. An
 * uparxei allos xarakthras 9a epistrafei -INVALID_PARAMTER_TYPE. */
int checkBase64(char *buf, unsigned int len) {
	unsigned int i;
	if(buf == NULL) return -INTERNAL_ERROR;
	if(strlen(buf) > len) return -INVALID_PARAMETER_VALUE;
	for(i=0;i<strlen(buf);i++) {
		if( isalpha(buf[i]) || isdigit(buf[i]) ) continue ;
		if( (buf[i] == '+')||(buf[i] == '/')||buf[i] == '=' ) continue ;
		
		return -INVALID_PARAMETER_TYPE;
	}
	return 0;
}

/* Epistrefei ton akeraio pou uparxei sto buf. Kaleitai mono afou
 * exei hdh klh9ei h checkInt */
long int parseInt(char *buf) {
	return( strtol(buf, NULL, 10) );
	
}

/* Epistrefei ton aproshmo pou uparxei sto buf. Kaleitai mono afou
 * exei hdh klh9ei h checkUnsignedInt */
unsigned long int parseUnsignedInt(char *buf) {
	return( strtoul(buf, NULL, 10) );
}

/* Epistrefei ton boolean pou uparxei sto buf. Kaleitai mono afou
 * exei hdh klh9ei h checkBoolean */
int parseBoolean(char *buf) {
	if(atoi(buf) == 0) return 0;
	else return 1;
}

/* Epistrefei to DateTime pou uparxei sto buf. Kaleitai mono afou
 * exei hdh klh9ei h checkDateTime */
DateTime parseDateTime(char *buf) {
	int i=0;
	while(isspace(buf[i]))i++;
	DateTime *dt=ascitodate(&buf[i]);
	DateTime dateTime = *dt;
	return dateTime;
}

